/*!\file  boot.S  The bootstrap code.
 *
 *      This file is part of the micro-rtos package.
 *
 *  Copyright (c) 2008-2009 by Gabriel Zabusek <gabriel.zabusek@gmail.com>
 *
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 */

/****************************************************************
* Bootcode for the LPC2103 microcontroller and probably for     *
* any arm7tdmi-s based mcu.                                     *
*                                                               *
* Author: Gabriel Zabusek, gabriel.zabusek@gmail.com            *
*         - under trademark of GZembedded software              *
*								*
* - note: make sure this code is linked to entry point address  *
*         usually 0x00000000                                    *
*                                                               *
* - features:                                                   *
*             * sets up the interrupt vector                    *
*             * implements the reset isr code                   *
*                                                               *
****************************************************************/

.equ    Mode_USR,       0x10
.equ    Mode_FIQ,       0x11
.equ    Mode_IRQ,       0x12
.equ    Mode_SVC,       0x13
.equ    Mode_ABT,       0x17
.equ    Mode_UND,       0x1B
.equ    Mode_SYS,       0x1F
.equ    I_BIT,          0x80
.equ    F_BIT,          0x40

.equ    Top_Stack,      0x40002000 /* Top of the LPC2103 RAM (8Kb in total) !!!This must be set correctly!!! */
.equ    UND_Stack_Size, 0x00000004 /*undefined*/
.equ    SVC_Stack_Size, 0x00000004 /*supervisor*/
.equ    ABT_Stack_Size, 0x00000004 /*abort*/
.equ    FIQ_Stack_Size, 0x00000004
.equ    IRQ_Stack_Size, 0x00000200 
.equ    USR_Stack_Size, 0x00000400 /*user*/
.equ    SYS_Stack_Size, 0x00000400 /*system*/


.text
.arm
.global _start
.func _start
_start:

IntVector:
                LDR     PC, RESET_ISR           /* address 0x00000000 - reset */
                LDR     PC, UNDEF_ISR           /* address 0x00000004 - undefined instruction */
                LDR     PC, SWINT_ISR           /* address 0x00000008 - software interrupt */
                LDR     PC, PFABT_ISR           /* address 0x0000000C - prefetch abort */
                LDR     PC, DTABT_ISR           /* address 0x00000010 - data abort */
                NOP                             /* address 0x00000014 - reserved */
		LDR	PC, IRQ_ISR
                LDR     PC, [PC, #-0xFF0]      /* address 0x00000018 - interrupt requests - VIC */
                LDR     PC, FIQ_ISR             /* address 0x0000001C - fast interrupt requests */

RESET_ISR:      .word   F_RESET_ISR /* reset handler */
UNDEF_ISR:      .word   UNHANDLED 
SWINT_ISR:      .word   swi_h	    /* sw irq handler */ 
PFABT_ISR:      .word   UNHANDLED 
DTABT_ISR:      .word   UNHANDLED 
                .word   0
IRQ_ISR:	.word	irq_h       /* irq handler */
FIQ_ISR:        .word   UNHANDLED

UNHANDLED:
	B UNHANDLED

F_RESET_ISR:


/*
 * Initialise Interrupt System
 */
        LDR     R0, =Top_Stack          /*Setup Stack for each mode*/

/*Enter Undefined Instruction Mode and set its Stack Pointer*/
        MSR     CPSR_c, #(Mode_UND | I_BIT | F_BIT)
        MOV     SP, R0
        SUB     R0, R0, #UND_Stack_Size

/*Enter Abort Mode and set its Stack Pointer*/
        MSR     CPSR_c, #(Mode_ABT | I_BIT | F_BIT)
        MOV     SP, R0
        SUB     R0, R0, #ABT_Stack_Size

/*Enter FIQ Mode and set its Stack Pointer*/
        MSR     CPSR_c, #(Mode_FIQ | I_BIT | F_BIT)
        MOV     SP, R0
        SUB     R0, R0, #FIQ_Stack_Size

/*Enter IRQ Mode and set its Stack Pointer*/
        MSR     CPSR_c, #(Mode_IRQ | I_BIT | F_BIT)
        MOV     SP, R0
        SUB     R0, R0, #IRQ_Stack_Size

/*Enter Supervisor Mode and set its Stack Pointer*/
        MSR     CPSR_c, #(Mode_SVC | I_BIT | F_BIT)
        MOV     SP, R0
        SUB     R0, R0, #SVC_Stack_Size

/*Enter Sysem Mode and set its Stack Pointer*/
	MSR	CPSR_c, #(Mode_SYS | I_BIT | F_BIT)
	MOV	SP, R0

/*all SPs set so go ahead and start in the supervisor mode with irq/fiq not enabled*/
	MSR	CPSR_c, #(Mode_SVC | I_BIT | F_BIT)


/*
 * Relocate .data section (Copy from ROM to RAM)
 */
        LDR     R1, =_etext
        LDR     R2, =.data
        LDR     R3, =_edata
LoopRel:
        CMP     R2, R3
        LDRLO   R0, [R1], #4
        STRLO   R0, [R2], #4
        BLO     LoopRel

/*
 * Clear .bss section (Zero init)
 */
        MOV     R0, #0
        LDR     R1, =__bss_start__
        LDR     R2, =__bss_end__
LoopZI:
        CMP     R1, R2
        STRLO   R0, [R1], #4
        BLO     LoopZI

/*
* Jump to boot_init C code -> 2nd stage basic hardware initializations
*/
	ADR	LR, __boot_init_exit
	LDR	R0, =boot_init
	BX	R0

__boot_init_exit:
	B	__boot_init_exit

.size _start, . - _start
.endfunc
.end
